package edu.upenn.cis.cis555.webserver;

import java.util.Enumeration;
import java.util.Properties;

import javax.servlet.http.HttpSessionContext;

@SuppressWarnings("deprecation")
public class HttpSession implements javax.servlet.http.HttpSession {
	
	private Properties m_props = new Properties();
	private boolean m_valid;
	private boolean is_new;
	private long creationTime;
	private ServletContext theServletContext;
	private String sid;
	private long last_accessed_time; //milliseconds since 1970
	
	public HttpSession(String id) {
		creationTime = System.currentTimeMillis();
		last_accessed_time = creationTime;
		sid = id;
		is_new = true;
		m_valid = true;
	}
	
	public void setLastAccessedTime(long time) {
		last_accessed_time = time;
		is_new = false;
	}
	
	boolean isValid() {
		return m_valid;
	}
	
	@Override //DONE
	public long getCreationTime() {
		// Returns the time when this session was created, measured in milliseconds since midnight January 1, 1970 GMT. 
		return creationTime;
	}

	@Override //DONE
	public String getId() {
		// Returns a string containing the unique identifier assigned to this session. The identifier 
		// is assigned by the servlet container and is implementation dependent. 
		return sid;
	}

	@Override //DONE
	public long getLastAccessedTime() {
//	    Returns the last time the client sent a request associated with this session, as the number of milliseconds 
//	    since midnight January 1, 1970 GMT, and marked by the time the container received the request.
//
//	    Actions that your application takes, such as getting or setting a value associated with the session, do not affect 
//	    the access time.
//
//	    Returns:
//	        a long representing the last time the client sent a request associated with this session, expressed in milliseconds 
//	        since 1/1/1970 GMT 
//	    Throws:
//	        java.lang.IllegalStateException - if this method is called on an invalidated session
		if (!isValid())
			throw new IllegalStateException();
		else
			return last_accessed_time;
	}
	
	@Override //DONE
	public ServletContext getServletContext() {
		// Returns the ServletContext to which this session belongs. 
		return theServletContext;
	}
	
	@Override //DONE
	public void setMaxInactiveInterval(int arg0) {
		// Specifies the time, in seconds, between client requests before the servlet container will invalidate this session. 
		// A negative time indicates the session should never timeout.
		HttpServer.session_timeout = arg0/60;
	}

	@Override //DONE
	public int getMaxInactiveInterval() {
//	    Returns the maximum time interval, in seconds, that the servlet container will keep this session open between 
//	    client accesses. After this interval, the servlet container will invalidate the session. The maximum time interval 
//	    can be set with the setMaxInactiveInterval method. A negative time indicates the session should never timeout.
//
//	    Returns:
//	        an integer specifying the number of seconds this session remains open between client requests
		return HttpServer.session_timeout*60;
	}
	
	@Override //DONE
	public Object getAttribute(String name) {
		// Returns the object bound with the specified name in this session, or null if no object is bound under the name. 
		return m_props.get(name);
	}

	@Override //DONE
	public Enumeration<?> getAttributeNames() {
		// Returns an Enumeration of String objects containing the names of all the objects bound to this session. 
		return m_props.keys();
	}
	
	@Override //DONE
	public void setAttribute(String name, Object value) {
//	    Binds an object to this session, using the name specified. If an object of the same name is already bound to the session, 
//	    the object is replaced.
//
//	    After this method executes, and if the new object implements HttpSessionBindingListener, the container calls 
//	    HttpSessionBindingListener.valueBound. The container then notifies any HttpSessionAttributeListeners in the web application.
//
//	    If an object was already bound to this session of this name that implements HttpSessionBindingListener, its 
//	    HttpSessionBindingListener.valueUnbound method is called.
//
//	    If the value passed in is null, this has the same effect as calling removeAttribute().
//
//	    Parameters:
//	        name - the name to which the object is bound; cannot be null
//	        value - the object to be bound 
//	    Throws:
//	        java.lang.IllegalStateException - if this method is called on an invalidated session
		if (!isValid())
			throw new IllegalStateException();
		else {
			if (value == null)
				removeAttribute(name);
			else
				m_props.put(name, value);
		}
	}
	
	@Override //DONE
	public void removeAttribute(String name) {
//	    Removes the object bound with the specified name from this session. If the session does not have an object bound with 
//	    the specified name, this method does nothing.
//
//	    After this method executes, and if the object implements HttpSessionBindingListener, the container calls 
//	    HttpSessionBindingListener.valueUnbound. The container then notifies any HttpSessionAttributeListeners in the web application.
//
//	    Parameters:
//	        name - the name of the object to remove from this session 
//	    Throws:
//	        java.lang.IllegalStateException - if this method is called on an invalidated session
		if (!isValid())
			throw new IllegalStateException();
		else
			m_props.remove(name);
	}

	@Override //DONE
	public void invalidate() {
//	    Invalidates this session then unbinds any objects bound to it.
//
//	    Throws:
//	        java.lang.IllegalStateException - if this method is called on an already invalidated session
		if (m_valid == false)
			throw new IllegalStateException();
		else
			m_valid = false;
	}

	@Override //DONE
	public boolean isNew() {
//	    Returns true if the client does not yet know about the session or if the client chooses not to join the session. For example, 
//	    if the server used only cookie-based sessions, and the client had disabled the use of cookies, then a session would be new 
//	    on each request.
//
//	    Returns:
//	        true if the server has created a session, but the client has not yet joined 
//	    Throws:
//	        java.lang.IllegalStateException - if this method is called on an already invalidated session
		if (!isValid())
			throw new IllegalStateException();
		else
			return is_new;
	}
	
	@Override //DONE
	public HttpSessionContext getSessionContext() {
		// Deprecated. As of Version 2.1, this method is deprecated and has no replacement.
		return null;
	}
	
	@Override //DONE
	public Object getValue(String arg0) {
		// Deprecated. As of Version 2.2, this method is replaced by getAttribute(java.lang.String).
		// return m_props.get(arg0);
		return null;
	}
	
	@Override //DONE
	public String[] getValueNames() {
		// Deprecated. As of Version 2.2, this method is replaced by getAttributeNames()
		return null;
	}
	
	@Override //DONE
	public void putValue(String arg0, Object arg1) {
		// Deprecated. As of Version 2.2, this method is replaced by setAttribute(java.lang.String, java.lang.Object)
		// m_props.put(arg0, arg1);
	}
	
	@Override //DONE
	public void removeValue(String arg0) {
		// Deprecated. As of Version 2.2, this method is replaced by removeAttribute(java.lang.String)
		// m_props.remove(arg0);
	}

}
